package com.huiyeji.dynamic.core;

import com.huiyeji.dynamic.core.exception.DynamicException;
import com.huiyeji.dynamic.core.exception.DynamicStatementParseException;

import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Huiyeji
 */
public class DynamicEngine {

    private final DynamicContext context;

    protected DynamicEngine(Map<String, Object> globalContextMap, DynamicObjectFactory factory,DynamicPluginManager pluginManager){
        this.context = new DynamicContext(globalContextMap,factory,pluginManager);
    }

    public DynamicEngine(Map<String, Object> globalContextMap, DynamicObjectFactory factory){
        this(globalContextMap,factory,null);
    }

    public DynamicEngine(DynamicObjectFactory factory){
        this(null,factory);
    }

    protected DynamicEngine(DynamicPluginManager pluginManager){
        this(null,DynamicObjectFactory.createFactory(),pluginManager);
    }

    public DynamicEngine(){
        this(DynamicObjectFactory.createFactory());
    }

    public void tempLoad(Map<String,Object> tempData){
        context.tempLoad(tempData);
    }

    public void loadStatements(List<String> statements){
        parseStatements(statements);
    }

    public DynamicObjectFactory getFactory(){
        return context.getFactory();
    }

    public DynamicContext getContext() {
        return context;
    }

    protected Map<String,Object> getReturnData() {
        return context.getReturnData();
    }

    public DynamicResult process() {
        return processInternal(false);
    }

    public DynamicResult process(List<String> statements) {

        //解析动态代码语句
        parseStatements(statements);

        return processInternal(true);
    }

    private DynamicResult processInternal(boolean clearPointer){
        try {
            executeStatement();
            return new DynamicSuccessResult(context);
        } catch (DynamicException dynamicException){
            return new DynamicErrorResult(new DynamicException(dynamicException.getCode(),"HSP Dynamic Engine Process Error : " + dynamicException.getMessage()),context);
        } catch (Exception exception){
            return new DynamicErrorResult(exception,context);
        } finally {
            context.tempClear(clearPointer);
        }
    }

    private void executeStatement(){
        DynamicStatementPointer pointer = context.getPointer();
        while (pointer.hasNext()){
            context.getExecutor().execute(context,pointer.next());
        }
    }

    private void parseStatements(List<String> statements) {
        context.setPointer(parse(statements));
    }

    protected DynamicStatementPointer parse(List<String> statements){
        List<DynamicStatement> dynamicStatements = new ArrayList<>();
        String realStatement = null;
        try {
            for (String statement : statements) {
                realStatement = statement.trim();
                dynamicStatements.add(context.getParserMatcher().matchObject(realStatement).parse(context,realStatement));
            }
            return new DynamicStatementPointer(dynamicStatements);
        }catch (Exception exception){
            throw new DynamicStatementParseException(exception.getMessage() + "\n    at 【 " + realStatement + " 】");
        }
    }

    public static void main(String[] args) throws IOException, AWTException {
        DynamicObject spring = DynamicBuilderManager.Anno.build("TEST-SPRING");
        spring.setDynamicObjectName("Spring");
        DynamicObjectFactory dynamicObjectFactory = DynamicObjectFactory.createFactory(spring);
        DynamicEngine engine = new DynamicEngine(dynamicObjectFactory);
        List<String> statements = new ArrayList<String>();
//        statements.add("123 (123)");
        statements.add("//Dynamic testMap = map.create()");
        statements.add("         //Dynamic testMap = map.create()");
        statements.add("          ");
        statements.add("");




        statements.add("Dynamic list1 = list.of('3','3232')");
//        statements.add("program.error()");
//        statements.add("list1.add('1dawd')");
//        statements.add("list1.add('123222')");
//        statements.add("list1.add('1dadawd')");
//        statements.add("list1.add('1ff21')");

        statements.add("Dynamic listDemo = class.createObject('java.util.ArrayList')");
        statements.add("monitor.any('test')");
        statements.add("listDemo.add(list1)");
        statements.add("newList = class.createObject('java.util.ArrayList',list.of(list.of('dawd','awdaw3','444')))");
        statements.add("//Dynamic testMap = map.create()");
        statements.add("//Dynamic testMap = map.create()");
        statements.add("//Dynamic testMap = map.create()");
        statements.add("//Dynamic testMap = map.create()");

        statements.add("Dynamic paramList = list.createList()");
        statements.add("paramList.add('张三')");
        statements.add("paramList.add('男')");
        statements.add("paramList.add('有')");
        statements.add("//Demo = class.createObject2('com.gillion.mdm.masterdata.dynamic.bean.Demo',paramList)");
        statements.add("//Dynamic.dynamic(Demo)");
        statements.add("//Dynamic testMap = map.create()");
        statements.add("//Dynamic testMap = map.create()");


        statements.add("//testMap.put('name','梨花')");
        statements.add("//testMap.put('age',string.toInteger('23'))");
        statements.add("//testMap.put('sex' ,'女')");
        statements.add("//Dynamic list = testMap.values()");
        statements.add("Dynamic iterator = program.for(   list1.size()  ,'index')");
        statements.add("result = string.of('')");
        statements.add("iterator.start()");
        statements.add("temp = list1.get(    index        )");
        statements.add("//iterator.continue()");
        statements.add("//temp = string.of('【${item.key}】:【${item.value}】')");
        statements.add("Dynamic condition = program.if(object.equals(context.get('result'),''))");
        statements.add("condition.true(    )");
        statements.add("result = string.of(temp  )");
        statements.add("condition.false(  )");
        statements.add("result = string.of(  '${result}-${temp}'  )");
        statements.add("condition.end()");
        statements.add("iterator.end()");
        statements.add("context.return('result')");
        statements.add("context.return('newList')");
        statements.add("context.set('intTest1', 999 )");
        statements.add("context.return('intTest1dawdasd',  intTest1 == intTest1 )");
        statements.add("  intTest1  ++   ");
        statements.add("  intTest1  --   ");
        statements.add("  intTest1  ++   ");
        statements.add("  intTest1  ++   ");

        statements.add("Static.dynamic('com.huiyeji.dynamic.core.bean.DynamicString')");
        statements.add("R23Coder = Static.dynamic('com.huiyeji.crypt._R_2_3_Coder')");
        statements.add("DynamicString.test()");
        statements.add("program.print(R23Coder.decode('8KJSKU9s9Ye19d9exw9exTx'))");
        statements.add("monitor.any()");

        statements.add("context.return('intTest1')");
//        statements.add("program.end()");
        statements.add("monitor.one('condition')");
        statements.add("sql = string.of('update ${tableName} set ${appkeyName} = <#2>${value@appKey}<#2> where ${originalCodeName} = <#2>${value@originalCode}<#2> and ${companyCodeName} = <#2>${value@companyCode}<#2>')");
        statements.add("monitor.one('context')");
        statements.add("monitor.one('paramList')");
        statements.add("return uuid = string.uuid()");
        statements.add("//monitor.one('string1')");
        statements.add("string1 = 45645645");
        statements.add("//monitor.one(string1)");
        statements.add("context.return('string1','abc')");
        statements.add("//uuid ++");
        statements.add("//context.return('Demo'   )");
        statements.add("//return name = demo.getName()");
        statements.add("//monitor.one('string1')");
        statements.add("rootData = '测试root 1233423'");
        statements.add("//R2Coder.decodeFile('C:/Users/HW/Desktop/Test2Plugin.hsp.dy.plugin')");
        statements.add("//plugin.install('file:/C:/Users/HW/Desktop/plugins/timer.hsp.dy.plugin')");
        statements.add("//plugin.install('file:C:/Users/HW/Desktop/plugins/PluginScanner.hsp.dy.plugin')");
        statements.add("//plugin.uninstall('pos')");
        statements.add("//PluginScanner.scan('plugins')");
        statements.add("//program.print(pos.test())");
        statements.add("//plugin.import('file:/C:/Users/HW/Desktop/Test2Plugin.hsp.dy.plugin')");
        statements.add("//plugin.import('file:/C:/Users/HW/Desktop/hsp.dy.plugin-Hsp Dynamic 引擎插件/MasterDataService.hsp.dy.plugin')");
        statements.add("//plugin.uninstall()");
        statements.add("//return data = TestPlugin.do('PARTNER1','')");
        statements.add("//program.sleep(3)");
        statements.add("program.print('主线程----${data}')");
        statements.add("//program.sleep(3)");
        statements.add("//timer.start()");
        statements.add("//program.print(timer.now())");
        statements.add("//end = timer.end()");
        statements.add("//program.print('共耗时======${end}')");
        statements.add("//TestPlugin dafefas = string.of('dawd')");
        statements.add("//program.error('打印测试${data}')");
        statements.add("//return data = Test2Plugin.getMasterData(5,10)");
        statements.add("//timer.doTest('','78768876,,,,8678678')");
        statements.add("//return data = R3Coder.decode('W58GB0sSsGBXsUsaBBsCsxB0sNs')");
        statements.add("//program.print(R3Coder.decode('W580s0s0sGB0sSs0s0s0sGBXsUs0s0s0saBBsCs0s0s0sxB0sNs'))");
        statements.add("");
        engine.loadStatements(statements);
        DynamicResult result = engine.process();
        System.out.println(result);
        if (!result.isSuccess()){
            DynamicErrorResult errorResult = (DynamicErrorResult) result;
            errorResult.throwException();
        }
    }
}
